<?php

declare(strict_types=1);

use App\Model\Article;
use Hyperf\Database\Seeders\Seeder;
use Hyperf\DbConnection\Db;

class UserSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        // 填充数据，所有带有统计效果的 *_count字段都是随机的，不是真实数据值
        $faker = \Faker\Factory::create('zh_CN');

        $this->createUsers($faker); // 101

        $this->createArticles($faker); // 每个用户2-6个

        $this->createArticleCategories($faker); // 100个分类，每个分类有2个关联文章

        $this->createArticleTags($faker); // 100个标签，每个标签关联2个文章

        $this->createArticleFavorites($faker); // 每个用户与2个文章关联

        $this->createArticleLikes($faker); // 每个用户与2个文章关联

        $this->createComments($faker); // 每个文章生成2条评论，随机50%的可能，生成每个评论的点赞，每个评论生成一个子评论
    }

    private function createComments(\Faker\Generator $faker)
    {
        $maxArticleId = Article::max('id');
        $maxSubCommentId = 0;

        foreach (range(1, $maxArticleId) as $articleId) {
            foreach (range(1, 2) as $index) {
                $data = [
                    'user_id' => $faker->numberBetween(1, 101),
                    'article_id' => $articleId,
                    'parent_id' => null,
                    'content' => $faker->text,
                    'like_count' => $faker->numberBetween(1, 10),
                    'status' => $faker->randomElement(['pending','approved','rejected']),
                    'created_at' => $faker->dateTime->format('Y-m-d H:i:s'),
                    'updated_at' => $faker->dateTime->format('Y-m-d H:i:s'),
                ];
                $comment = \App\Model\Comment::create($data);
                $subComment = $comment->subComments()->create([
                    'user_id' => $faker->numberBetween(1, 101),
                    'article_id' => $articleId,
                    'content' => $faker->text,
                    'like_count' => $faker->numberBetween(1, 10),
                    'status' => $faker->randomElement(['pending','approved','rejected']),
                    'created_at' => $faker->dateTime->format('Y-m-d H:i:s'),
                    'updated_at' => $faker->dateTime->format('Y-m-d H:i:s'),
                ]);
                $maxSubCommentId = $subComment->id;
            }
        }

        $data = [];
        foreach(range(1, $maxSubCommentId) as $index) {
            if ($faker->boolean) {
                continue;
            }

            $data[] = [
                'user_id' => $faker->numberBetween(1, 101),
                'comment_id' => $index,
                'created_at' => $faker->dateTime->format('Y-m-d H:i:s'),
            ];

            if (count($data) > 100) {
                Db::table('comment_likes')->insert($data);
                $data = [];
            }
        }

        if (count($data) > 0) {
            Db::table('comment_likes')->insert($data);
        }
    }

    private function createArticleLikes(\Faker\Generator $faker)
    {
        $data = [];
        $maxArticleId = Article::max('id');

        foreach (range(1, 101) as $userId) {
            $data[] = [
                'user_id' => $userId,
                'article_id' => $faker->numberBetween(1, ceil($maxArticleId/2)),
                'created_at' => $faker->dateTime->format('Y-m-d H:i:s'),
            ];
            $data[] = [
                'user_id' => $userId,
                'article_id' => $faker->numberBetween(ceil($maxArticleId/2), $maxArticleId),
                'created_at' => $faker->dateTime->format('Y-m-d H:i:s'),
            ];
        }

        Db::table('article_likes')->insert($data);
    }

    private function createArticleFavorites(\Faker\Generator $faker)
    {
        $data = [];
        $maxArticleId = Article::max('id');

        foreach (range(1, 101) as $userId) {
            $data[] = [
                'user_id' => $userId,
                'article_id' => $faker->numberBetween(1, ceil($maxArticleId/2)),
                'folder' => $faker->word,
                'created_at' => $faker->dateTime->format('Y-m-d H:i:s'),
            ];
            $data[] = [
                'user_id' => $userId,
                'article_id' => $faker->numberBetween(ceil($maxArticleId/2), $maxArticleId),
                'folder' => $faker->word,
                'created_at' => $faker->dateTime->format('Y-m-d H:i:s'),
            ];
        }

        Db::table('article_favorites')->insert($data);
    }

    private function createArticleTags(\Faker\Generator $faker)
    {
        $data = [];

        foreach (range(1, 100) as $index) {
            $data[] = [
                'name' => substr($faker->uuid, 0, 45),
                'slug' => substr($faker->uuid, 0, 45),
                'description' => $faker->text,
                'color' => $faker->hexColor,
                'article_count' => $faker->numberBetween(1, 100),
                'created_at' => $faker->dateTime->format('Y-m-d H:i:s'),
                'updated_at' => $faker->dateTime->format('Y-m-d H:i:s')
            ];
        }

        Db::table('tags')->insert($data);

        $maxArticleId = Article::max('id');

        $data = [];
        foreach (range(1, 100) as $index) {
            $data[] = [
                'tag_id' => $index,
                'article_id' => $faker->numberBetween(1, ceil($maxArticleId/2)),
                'created_at' => $faker->dateTime->format('Y-m-d H:i:s'),
            ];
            $data[] = [
                'tag_id' => $index,
                'article_id' => $faker->numberBetween(floor($maxArticleId/2), $maxArticleId),
                'created_at' => $faker->dateTime->format('Y-m-d H:i:s'),
            ];
        }

        Db::table('article_tag')->insert($data);
    }

    private function createArticleCategories(\Faker\Generator $faker)
    {
        $data = [];

        foreach (range(1, 100) as $index) {
            $data[] = [
                'parent_id' => $index === 1 ? null : $faker->randomElement([null, $faker->numberBetween(1, $index)]),
                'name' => $faker->word,
                'slug' => $faker->slug,
                'description' => $faker->text,
                'icon' => $faker->imageUrl(64, 64),
                'order' => $faker->numberBetween(1, 100),
                'article_count' => $faker->numberBetween(1, 100),
                'created_at' => $faker->dateTime->format('Y-m-d H:i:s'),
                'updated_at' => $faker->dateTime->format('Y-m-d H:i:s')
            ];
        }

        Db::table('categories')->insert($data);

        $maxArticleId = Article::max('id');

        $data = [];
        foreach (range(1, 100) as $index) {
            $data[] = [
                'category_id' => $index,
                'article_id' => $faker->numberBetween(1, ceil($maxArticleId/2)),
                'created_at' => $faker->dateTime->format('Y-m-d H:i:s'),
            ];
            $data[] = [
                'category_id' => $index,
                'article_id' => $faker->numberBetween(floor($maxArticleId/2), $maxArticleId),
                'created_at' => $faker->dateTime->format('Y-m-d H:i:s'),
            ];
        }

        Db::table('article_category')->insert($data);
    }

    private function createArticles(\Faker\Generator $faker)
    {
        $articles = [];

        foreach (range(1, 100) as $index) {
            foreach (range(1, random_int(2, 6)) as $item) {
                $articles[] = [
                    'user_id' => $index,
                    'title' => $faker->text(30),
                    'content' => $faker->text,
                    'slug' => $faker->slug,
                    'summary' => $faker->text,
                    'content_type' => $faker->randomElement(['html', 'markdown']),
                    'cover_image' => $faker->imageUrl,
                    'status' => $faker->randomElement(['draft', 'review', 'published', 'archived']),
                    'view_count' => random_int(100, 1000000),
                    'like_count' => random_int(100, 1000000),
                    'comment_count' => random_int(100, 1000000),
                    'favorite_count' => random_int(100, 1000000),
                    'reading_time' => random_int(100, 1000),
                    'published_at' => $faker->randomElement([$faker->dateTime()->format('Y-m-d H:i:s'), null]),
                    'created_at' => $faker->dateTime()->format('Y-m-d H:i:s'),
                    'updated_at' => $faker->dateTime()->format('Y-m-d H:i:s'),
                ];
            }
        }

        DB::table('articles')->insert($articles);
    }

    private function createUsers(\Faker\Generator $faker)
    {
        $data = [];

        \App\Model\User::create([
            'name' => 'admin',
            'email' => 'admin@admin.com',
            'password' => password_hash('666666', PASSWORD_BCRYPT),
            'avatar' => $faker->imageUrl,
            'role' => 'admin',
            'points' => 1000,
            'status' => 'active',
            'last_login_at' => $faker->dateTime,
            'last_login_ip' => $faker->ipv4,
            'email_verified_at' => $faker->dateTime,
        ]);

        foreach (range(1, 100) as $index) {
            $data[] = [
                'name' => \Hyperf\Utils\Str::random(6),
                'email' => \Hyperf\Utils\Str::random(6) . '@example.com',
                'password' => password_hash('666666', PASSWORD_BCRYPT),
                'avatar' => $faker->imageUrl(),
                'role' => $faker->randomElement(['admin', 'user', 'author']),
                'points' => $faker->numberBetween(0, 10000),
                'status' => $faker->randomElement(['active', 'inactive', 'banned']),
                'last_login_at' => $faker->dateTime()->format('Y-m-d H:i:s'),
                'last_login_ip' => $faker->ipv4(),
                'email_verified_at' => $faker->randomElement([$faker->dateTime()->format('Y-m-d H:i:s'), null]),
                'created_at' => $faker->dateTime()->format('Y-m-d H:i:s'),
                'updated_at' => $faker->dateTime()->format('Y-m-d H:i:s'),
            ];
        }

        Db::table('users')->insert($data);
    }
}
